/*
 * This program is free software; you can redistribute it and/or modify 
 * it under the terms of the GNU General Public License as published by 
 * the Free Software Foundation; either version 3 of the License, or 
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 
 * for more details.
 * 
 * You should have received a copy of the GNU General Public License along 
 * with this program; if not, write to the Free Software Foundation, Inc., 
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#include <QFile>
#include <QFileInfo>
#include <QSettings>
#include <QRegExp>
#include "futabaagent.h"
#include "log.h"
#include "components/board.h"
#include "network/request.h"
#include "text.h"

namespace Wishmaster
{
	FutabaAgent::FutabaAgent(const QString& host) : DefaultAgent(host),
		m_host(host)
	{
	}

	FutabaAgent::~FutabaAgent()
	{
	}
	
	void FutabaAgent::getCaptcha(const ThreadId& threadId)
	{
		if(m_recaptchaKey.isEmpty())
		{
			QUrl url("http://" + makeFullHostname(threadId.boardId()) + threadId.boardId());
			RequestPtr request = connector()->makeRequest(url.host(), url.path(), "GET");
			connector()->connectRequest(this, SLOT(resultRecaptchaKey(RequestPtr, const QByteArray&)), 0, request);
			connector()->queue(request);
		}
		else
		{
			doRequestCaptcha();
		}
		m_currentThreadId = threadId;
	}

	void FutabaAgent::makePost(const PostDescriptor& post, const QString& captcha)
	{
		m_post = post;

		HttpRequestPtr request = connector()->makeHttpRequest(m_recaptchaSite, m_recaptchaPath, "POST");
		connector()->connectRequest(this, SLOT(doMakePost(RequestPtr, const QByteArray&)), 0, request);
		request->addPostField("recaptcha_challenge_field", m_challenge);
		request->addPostField("recaptcha_response_field", captcha);
		connector()->queue(request);
	}

	void FutabaAgent::doMakePost(RequestPtr r, const QByteArray& data)
	{
		QRegExp rx("<textarea[^>]*>(.*)</textarea>");
		rx.setMinimal(true);
		if(rx.indexIn(QString(data)) < 0)
		{
			emit postingError(tr("Unable to submit captcha"));
			return;
		}
		m_challenge = rx.cap(1);
		PostDescriptor post = m_post;

		QString postscript = property("postscript").toString();
		postscript.replace("%BOARD%", post.board);
		postscript.replace("%THREADID%", QString::number(post.parent_thread.threadNumericId()));

		QString wholehost = m_host;
		if(property(QString("posthostprefix" + post.board).toUtf8().data()).isValid())
			wholehost.prepend(property(QString("posthostprefix" + post.board).toUtf8().data()).toString());

		QString referer = m_host;
		if(property(QString("hostprefix" + post.board).toUtf8().data()).isValid())
			referer.prepend(property(QString("hostprefix" + post.board).toUtf8().data()).toString());

		HttpRequestPtr request = connector()->makeHttpRequest(wholehost, postscript, "POST");
		request->setReferer(QString("http://%1%2res/%3").arg(referer).arg(post.board).arg(post.parent_thread.threadNumericId()));
		request->setProperty("thread", (unsigned int)post.parent_thread.threadNumericId());
		request->setProperty("board", post.board);
		request->addPostField("MAX_FILE_SIZE", "2097152");
		request->addPostField("resto", QString::number(post.parent_thread.threadNumericId()));
		request->addPostField("name", post.name);
		request->addPostField("email", post.email);
		request->addPostField("sub", post.topic);
		request->addPostField("com", post.text);
		request->addPostField("recaptcha_challenge_field", m_challenge);
		request->addPostField("recaptcha_response_field", "manual_challenge");
		addAttachments(request, post.attachments.count() > 0 ? post.attachments.at(0) : AttachmentDescriptor(), "upfile");
		request->addPostField("pwd", post.password);
		request->addPostField("mode", "regist");

		connector()->connectRequest(this, SLOT(resultPost(RequestPtr, const QByteArray&)), 0, request);
		connector()->queue(request);
	}

	void FutabaAgent::createThread(const PostDescriptor& post, const QString& captcha)
	{
		m_post = post;

		HttpRequestPtr request = connector()->makeHttpRequest(m_recaptchaSite, m_recaptchaPath, "POST");
		connector()->connectRequest(this, SLOT(doMakeThread(RequestPtr, const QByteArray&)), 0, request);
		request->addPostField("recaptcha_challenge_field", m_challenge);
		request->addPostField("recaptcha_response_field", captcha);
		connector()->queue(request);
	}

	void FutabaAgent::doCreateThread(RequestPtr r, const QByteArray& data)
	{
		QRegExp rx("<textarea[^>]*>(.*)</textarea>");
		rx.setMinimal(true);
		if(rx.indexIn(QString(data)) < 0)
		{
			emit postingError(tr("Unable to submit captcha"));
			return;
		}
		m_challenge = rx.cap(1);

		PostDescriptor post = m_post;

		QString postscript = property("postscript").toString();
		postscript.replace("%BOARD%", post.board);

		QString wholehost = m_host;
		if(property(QString("posthostprefix" + post.board).toUtf8().data()).isValid())
			wholehost.prepend(property(QString("posthostprefix" + post.board).toUtf8().data()).toString());

		HttpRequestPtr request = connector()->makeHttpRequest(wholehost, postscript, "POST");
		request->setProperty("thread", 0);
		request->setProperty("board", post.board);

		//request->addPostField("task", "post");
		request->addPostField("name", post.name);
		request->addPostField("email", post.email);
		request->addPostField("sub", post.topic);
		request->addPostField("com", post.text);
		addAttachments(request, post.attachments.count() > 0 ? post.attachments.at(0) : AttachmentDescriptor(), "upfile");
		request->addPostField("recaptcha_challenge_field", m_challenge);
		request->addPostField("recaptcha_response_field", "manual_challenge");
		request->addPostField("pwd", post.password);
		request->addPostField("mode", "regist");

		connector()->connectRequest(this, SLOT(resultPost(RequestPtr, const QByteArray&)), 0, request);
		connector()->queue(request);
	}

	void FutabaAgent::deleteThread(const ThreadId& threadId, const QString& password)
	{
		log(llWarning, "Futallaby thread deletion is not implemented yet!!!");
	}

	void FutabaAgent::deletePost(const PostId& postId, const QString& password)
	{
		log(llWarning, "Futallaby post deletion is not implemented yet!!!");
	}

	void FutabaAgent::resultPost(RequestPtr r, const QByteArray& data)
	{
		log(llDebug, "resultPost: %s:%d", qPrintable(r->property("board").toString()), r->property("thread").toUInt());
		//emit postingError("");
		emit postingDone(ThreadId(m_host, r->property("board").toString(), r->property("thread").toUInt()));
		emit refresh(ThreadId(m_host, r->property("board").toString(), r->property("thread").toUInt()), true);
	}

	void FutabaAgent::resultRecaptchaKey(RequestPtr r, const QByteArray& data)
	{
		QString html(data);
		QRegExp rx("src=\"http://api\\.recaptcha\\.net/challenge\\?k=(.*)\""); // TODO proper regexp
		rx.setMinimal(true);
		if(rx.indexIn(html) < 0)
		{
			log(llWarning, "Unable to find recaptcha key");
			return;
		}
		m_recaptchaKey = rx.cap(1);
		doRequestCaptcha();
	}

	void FutabaAgent::doRequestCaptcha()
	{
		QString path = QString("noscript?k=") + m_recaptchaKey;
		HttpRequestPtr request = connector()->makeHttpRequest("api.recaptcha.net", path);
		request->setProperty("recaptcha_host", "api.recaptcha.net");
		request->setProperty("recaptcha_path", path);
		connector()->connectRequest(this, SLOT(resultRecaptchaChallenge(RequestPtr, const QByteArray&)), 0, request);
		connector()->queue(request);
	}

	void FutabaAgent::resultRecaptchaChallenge(RequestPtr r, const QByteArray& data)
	{
		QString html(data);
		QRegExp rx("id=\"recaptcha_challenge_field\" value=\"(.*)\"");
		rx.setMinimal(true);
		if(rx.indexIn(html) < 0)
		{
			log(llWarning, "Unable to find recaptcha challenge");
			return;
		}
		m_challenge = rx.cap(1);

		m_recaptchaSite = r->property("recaptcha_host").toString();
		m_recaptchaPath = r->property("recaptcha_path").toString();
		QString path = m_recaptchaPath.section("?", 0, 0);
		path = chopped(path, "noscript");

		path.append(QString("image?c=") + m_challenge);

		RequestPtr request = connector()->makeRequest(m_recaptchaSite, path);
		connector()->connectRequest(this, SLOT(resultRecaptchaImage(RequestPtr, const QByteArray&)), 0, request);
		connector()->queue(request);
	}

	void FutabaAgent::resultRecaptchaImage(RequestPtr r, const QByteArray& data)
	{
		emit captcha(m_currentThreadId, data);
	}

	QStringList FutabaAgent::ratings()
	{
		return QStringList();
	}

	ChanAgent* FutabaAgent::clone(const QString& host)
	{
		return new FutabaAgent(host);
	}

	QString FutabaAgent::id()
	{
		return "futallaby";
	}
}

Q_EXPORT_PLUGIN2(futabaagent, Wishmaster::FutabaAgent)
